package tt.dz.biz.service.account;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;
import tt.dz.biz.annotation.MsLog;
import tt.dz.biz.dao.account.AccountingDAO;
import tt.dz.biz.dao.common.CommonDAO;
import tt.dz.biz.exception.BusinessException;
import tt.dz.biz.service.card.CardTypeService;
import tt.dz.common.DzConstants;
import tt.dz.common.DzConstants.BizType;
import tt.dz.common.DzConstants.PayType;
import tt.dz.common.DzConstants.accountingState;
import tt.dz.common.DzConstants.orderType;
import tt.dz.common.DzConstants.userType;
import tt.dz.common.LogUtil;
import tt.dz.vo.TranInfoVO;
import tt.dz.vo.TranSubVO;

@Repository("accountingRecordService")
public class AccountingRecordService
{
  @Resource(name="accountingRuleDAO")
  AccountingDAO accountingDAO;
  @Resource(name="cardTypeServiceImpl")
  private CardTypeService cardTypeService;
  @Resource(name="commonDAO")
  CommonDAO commonDAO;
  
  @MsLog(bizCode="recordDividendJob_01", bizName="查询待记账交易", bizType=DzConstants.BizType.JOB)
  public List<TranInfoVO> queryTranWaitingForAccounting()
  {
    try
    {
      return this.accountingDAO.queryTranInfoWaitForAccounting();
    }
    catch (Exception e)
    {
      LogUtil.error("查询待记账交易", e);
    }
    return new ArrayList();
  }
  
  @MsLog(bizCode="recordDividendJob_02", bizName="更新交易记录状态为记账中", bizType=DzConstants.BizType.JOB)
  public void updateTranInfoAccounting(List<TranInfoVO> tranInfoList)
    throws Exception
  {
    try
    {
      if (CollectionUtils.isEmpty(tranInfoList)) {
        return;
      }
      Date dbTime = this.commonDAO.getDBCurrentTime();
      for (Iterator localIterator = tranInfoList.iterator(); localIterator.hasNext();)
      {
    	  TranInfoVO tranInfoVO = (TranInfoVO)localIterator.next();
        tranInfoVO.setAccountState(DzConstants.accountingState.ACCOUTING.value());
        tranInfoVO.setStartAccountTime(dbTime);
      }
      TranInfoVO tranInfoVO;
      int[] rs = this.accountingDAO.updateAccountStateForTranInfo(tranInfoList);
      if (null == rs) {
        throw new BusinessException("更新交易记录状态为记账中失败，参数为：" + tranInfoList);
      }
      for (int i : rs) {
        if (i == 0) {
          throw new BusinessException("更新交易记录状态为记账中失败，参数为：" + tranInfoList);
        }
      }
    }
    catch (Exception e)
    {
      LogUtil.error("更新交易为记账中状态失败,参数为" + tranInfoList, e);
      throw e;
    }
  }
  
  public List<TranInfoVO> fillSubTranInfoForTranInfo(List<TranInfoVO> tranInfoList)
    throws Exception
  {
    try
    {
      if (CollectionUtils.isEmpty(tranInfoList)) {
        return new ArrayList();
      }
      List<TranSubVO> subTranList = null;
      for (TranInfoVO tranInfoVO : tranInfoList)
      {
        subTranList = this.accountingDAO.queryTranSubList(tranInfoVO);
        if (CollectionUtils.isEmpty(subTranList)) {
          tranInfoVO.setTranSubVOList(new ArrayList());
        } else {
          tranInfoVO.setTranSubVOList(subTranList);
        }
      }
      return tranInfoList;
    }
    catch (Exception e)
    {
      LogUtil.error("查询待记账交易", e);
      throw e;
    }
  }
  
  @MsLog(bizCode="recordDividendJob_03", bizName="保存所有分录", bizType=DzConstants.BizType.JOB)
  public void saveAccountDevidend(List<TranInfoVO> tranInfoList)
    throws Exception
  {
    fillSubTranInfoForTranInfo(tranInfoList);
    AccountDividendPOJO accountDividendPOJO = null;
    for (TranInfoVO tranInfoTmp : tranInfoList)
    {
      if (null == tranInfoTmp.getOriginalPayerType())
      {
        if (this.cardTypeService.getAllOuterCardType().contains(tranInfoTmp.getCardType())) {
          accountDividendPOJO = new OutOfflineCardToMerchantPOJO(tranInfoTmp);
        } else {
          LogUtil.error(getClass() + "->saveAccountDevidend:未找到记账业务场景，原消费用户类型为空，且又不是外部离线（现金）卡，交易号为：" + tranInfoTmp.getTradeNo());
        }
      }
      else if (DzConstants.userType.PERSONAL_CUSTOMER.value().equals(tranInfoTmp.getOriginalPayerType()))
      {
        if ((CollectionUtils.isEmpty(tranInfoTmp.getTranSubVOList())) || 
          (DzConstants.PayType.EWALLET_PAY.value().equals(tranInfoTmp.getPayTypeCode()))) {
          accountDividendPOJO = new OnlineCardToMerchantPOJO(tranInfoTmp);
        } else if (DzConstants.orderType.AFTER_PAYMENT.value().equals(tranInfoTmp.getOrderType())) {
          accountDividendPOJO = new IndividualToMerchantPOJO(tranInfoTmp);
        } else {
          accountDividendPOJO = new IndividualToMerchantForImprestPOJO(tranInfoTmp);
        }
      }
      else if ((DzConstants.userType.UNIFIEDPAY_CUSTOMER.value().equals(tranInfoTmp.getOriginalPayerType())) || 
        (DzConstants.userType.ENTERPRISE_CUSTOMER.value().equals(tranInfoTmp.getOriginalPayerType())))
      {
        accountDividendPOJO = new IndividualToMerchantPOJO(tranInfoTmp);
      }
      else if (DzConstants.userType.OFFLINE_CUSTOMER.value().equals(tranInfoTmp.getOriginalPayerType()))
      {
        accountDividendPOJO = new OfflineCardToMerchantPOJO(tranInfoTmp);
      }
      else if (DzConstants.userType.MERCHANT_CUSTOMER.value().equals(tranInfoTmp.getOriginalPayerType()))
      {
        if (DzConstants.userType.MERCHANT_CUSTOMER.value().equals(getReceiverType(tranInfoTmp))) {
          accountDividendPOJO = new MerchantToMerchantPOJO(tranInfoTmp);
        } else if (DzConstants.userType.OFFLINE_CUSTOMER.value().equals(getReceiverType(tranInfoTmp))) {
          accountDividendPOJO = new MerchantToOfflineCardPOJO(tranInfoTmp);
        } else {
          LogUtil.error(getClass() + "->saveAccountDevidend:未找到记账业务场景，原消费用户类型为【运营商】且收款方不是运营商或离线卡（现金卡），交易号为：" + tranInfoTmp.getTradeNo());
        }
      }
      else if (DzConstants.userType.OUT_OFFLINE_CUSTOMER.value().equals(tranInfoTmp.getOriginalPayerType()))
      {
        accountDividendPOJO = new OutOfflineCardToMerchantPOJO(tranInfoTmp);
      }
      else
      {
        LogUtil.error(getClass() + "->saveAccountDevidend:未找到记账业务场景，原消费用户类型不为空，且不在现有客户类型中。交易号为：" + tranInfoTmp.getTradeNo());
        continue;
      }
      accountDividendPOJO.saveEndAccounting();
    }
  }
  
  private Integer getReceiverType(TranInfoVO tranInfoTmp)
  {
    if (null != tranInfoTmp.getReceiverType()) {
      return tranInfoTmp.getReceiverType();
    }
    return ((TranSubVO)tranInfoTmp.getTranSubVOList().get(0)).getReceiverType();
  }
}
